package com.bdqn.qnnews.user.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bdqn.qnnews.articel.api.dto.ApAuthorDto;
import com.bdqn.qnnews.articel.api.feign.ArticleFeignClient;
import com.bdqn.qnnews.common.base.PageResult;
import com.bdqn.qnnews.common.base.R;
import com.bdqn.qnnews.common.base.ResultCode;
import com.bdqn.qnnews.common.constants.AdminConstants;
import com.bdqn.qnnews.rest.exception.ApplicationException;
import com.bdqn.qnnews.user.entity.ApUser;
import com.bdqn.qnnews.user.entity.ApUserRealname;
import com.bdqn.qnnews.user.mapper.ApUserMapper;
import com.bdqn.qnnews.user.mapper.ApUserRealnameMapper;
import com.bdqn.qnnews.user.service.ApUserRealnameService;
import com.bdqn.qnnews.user.vo.AuthVo;
import com.bdqn.qnnews.wemedia.api.dto.WmUserDto;
import com.bdqn.qnnews.wemedia.api.feign.WeMediaFeignClient;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;

/**
 * <p>
 * APP实名认证信息表 服务实现类
 * </p>
 *
 * @author xlz
 * @since 2023-12-19
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class ApUserRealnameServiceImpl extends ServiceImpl<ApUserRealnameMapper, ApUserRealname> implements ApUserRealnameService {

    private final ApUserMapper apUserMapper;
    private final ArticleFeignClient articleClient;
    private final WeMediaFeignClient weMediaClient;

    @Override
    public PageResult<List<ApUserRealname>> findList(AuthVo vo) {
        // 创建mybatisplus的分页数据对象
        final Page<ApUserRealname> page = new Page<>(vo.getPage(), vo.getSize());
        // 准备查询的条件
        final QueryWrapper<ApUserRealname> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(vo.getStatus() != null,"status",vo.getStatus());

        // 查询分页数据
        final Page<ApUserRealname> pageData = page(page, queryWrapper);

        //封装分页数据
        return PageResult.ok(ResultCode.SUCCESS,pageData.getRecords())
                .setCurrentPage(vo.getPage())
                .setTotal((int) pageData.getTotal())
                .setSize(vo.getSize());
    }

    // 开启事务 TM
    @GlobalTransactional(rollbackFor = Exception.class)
    //@Transactional(rollbackFor = Exception.class)
    @Override
    public R<String> updateStatusById(AuthVo vo, Byte authType) {
        // 1 参数检查
        if (vo.getId()==null) {
            throw new ApplicationException(ResultCode.PARAM_INVALID);
        }

        // 2 查询当前认证用户是否在 APP端有当前用户
        final LambdaQueryWrapper<ApUserRealname> queryWrapper =
                Wrappers.<ApUserRealname>lambdaQuery().eq(ApUserRealname::getId, vo.getId());

        ApUserRealname apUserRealname = getOne(queryWrapper);

        // 3. 判断当前认证信息是否存在
        if (apUserRealname == null) {
            log.error("待审核 实名认证信息不存在 userRealnameId:{}",vo.getId());
            throw new ApplicationException(ResultCode.DATA_NOT_EXIST);
        }

        // 4. 判断当前认证信息的状态是否为 ‘待审核’
        if (!AdminConstants.WAIT_AUTH.equals(apUserRealname.getStatus())) {
            log.error("实名认证信息非【待审核】状态  userRealnameId:{}", vo.getId());
            throw new ApplicationException(ResultCode.DATA_NOT_ALLOW);
        }

        // 5. 根据认证用户信息表id 去查询App用户信息
        // 条件为 ap_user表中的id = 认证用户信息表中的user_id
        ApUser apUser = apUserMapper.selectOne(Wrappers.<ApUser>lambdaQuery()
                .eq(ApUser::getId, apUserRealname.getUserId()));
        if(apUser == null){
            log.error("实名认证信息 关联 app的用户不存在  userRealnameId:{}, userId:{} ",
                    vo.getId(),
                    apUserRealname.getUserId());
            throw new ApplicationException(ResultCode.DATA_NOT_EXIST);
        }

        // 6. 更新认证用户信息
        // 6.1 修改认证状态
        apUserRealname.setStatus(authType);
        // 修改更新时间位当前日期时间
        apUserRealname.setUpdatedTime(LocalDateTime.now());
        // 如果消息字段不为空，设置消息字段
        if(StringUtils.isNotBlank(vo.getMsg())){
            apUserRealname.setReason(vo.getMsg());
        }
        // 更新认证信息
        updateById(apUserRealname);

        // 如果状态为 9 时，还需要远程调用自媒体服务和文章服务创建和绑定用户信息
        // 7. 认证状态如果为 通过
        if (AdminConstants.PASS_AUTH.equals(authType)) {

            //7.1 远程调用自媒体微服务创建自媒体账户
            final WmUserDto wmUserDto = createWmUser(apUser);

            //7.2 远程调用app文章微服务创建作者信息
            createAuthor(apUser,wmUserDto);
        }

        // 8. 返回认证结果
        return R.ok("实名认证通过","认证用户id:"+apUser.getId());
    }

    /**
     * 创建自媒体用户信息
     * @param apUser app用户信息
     * @return
     */
    private WmUserDto createWmUser(ApUser apUser) {
        R<WmUserDto> dtoR = weMediaClient.findByName(apUser.getName());
        if (dtoR.getCode() != 200){
            throw new ApplicationException(ResultCode.SERVER_ERROR,dtoR.getErrorMessage());
        }
        WmUserDto wmUserDto = dtoR.getData();
        if (wmUserDto != null){
            throw new ApplicationException("自媒体用户信息已经存在");
        }

        wmUserDto = new WmUserDto();
        wmUserDto.setName(apUser.getName());
        wmUserDto.setPassword(apUser.getPassword());
        wmUserDto.setApUserId(apUser.getId());
        wmUserDto.setPhone(apUser.getPhone());
        wmUserDto.setImage(apUser.getImage());
        // 设置自媒体用户类型为个人用户
        wmUserDto.setType(AdminConstants.AUTHOR_TYPE);
        wmUserDto.setCreatedTime(LocalDateTime.now());
        // 设置状态为正常使用
        wmUserDto.setStatus((byte) 9);

        // 4. 远程保存自媒体用户数据
        final R<WmUserDto> saveR = weMediaClient.save(wmUserDto);
        if (saveR.getCode() != 200){
            throw new ApplicationException(ResultCode.SERVER_ERROR,saveR.getErrorMessage());
        }
        // 返回保存成功后的自媒体用户信息
        return saveR.getData();
    }

    /**
     * 远程创建文章作者信息
     * @param apUser app用户信息
     * @param wmUserDto 自媒体用户信息
     */
    private void createAuthor(ApUser apUser, WmUserDto wmUserDto) {
        final R<ApAuthorDto> dtoR = articleClient.getByApUserId(apUser.getId());
        if (dtoR.getCode() != 200){
            throw new ApplicationException(ResultCode.SERVER_ERROR,dtoR.getErrorMessage());
        }
        final ApAuthorDto authorDto = dtoR.getData();
        if (authorDto != null){
            throw new ApplicationException("app文章作者信息已经存在");
        }

        final ApAuthorDto apAuthorDto = new ApAuthorDto();
        apAuthorDto.setName(apUser.getName());
        // 设置作者类型
        apAuthorDto.setType(AdminConstants.AUTHOR_TYPE);
        apAuthorDto.setCreatedTime(LocalDateTime.now());
        // 设置app用户id
        apAuthorDto.setUserId(apUser.getId());
        // 设置自媒体用户id
        apAuthorDto.setWmUserId(wmUserDto.getId());
        // 保存
        final R<String> saveR = articleClient.save(apAuthorDto);
        if (saveR.getCode() != 200){
            throw new ApplicationException(ResultCode.SERVER_ERROR,saveR.getErrorMessage());
        }
    }
}
